#include <string>
#include <assert.h>

#include "c_ResourceMgr.h"
#include "c_SpriteResource.h"
#include "c_TextureResource.h"

wiigi::c_ResourceMgr::c_ResourceMgr(void)
{
   init();
}

wiigi::c_ResourceMgr::c_ResourceMgr( std::string& ScriptName )
{
   init();

   loadScript( ScriptName );
}

wiigi::c_ResourceMgr::~c_ResourceMgr(void)
{
   deleteResources();
}
   
void wiigi::c_ResourceMgr::init( void )
{
   m_GroupMap.clear();
   m_Resources.clear();
   m_NameMap.clear();
}

bool wiigi::c_ResourceMgr::loadScript( const std::string& ScriptName )
{
   printf("c_ResourceMgr::loadScript:%s\n", ScriptName.c_str() );
   
   loadScript( ScriptName, m_Resources );
   
   const int NumOfResources = m_Resources.size();
   printf( "Fnd %u resources\n", NumOfResources );
   
   for( std::list<c_Resource*>::iterator it = m_Resources.begin(); it != m_Resources.end();  )
   {
      c_Resource* Resource;
      Resource = *it;
      assert( Resource != 0 );
      
      printf( "processing %s\n", Resource->getName().c_str() );

      if( m_NameMap.count( Resource->getName() ) )
      {
         printf( "erase %s\n", Resource->getName().c_str() );
         
         delete Resource;
         it = m_Resources.erase( it );
      }
      else
      {
         //Add to list
         m_NameMap.insert( make_pair(Resource->getName(), Resource ) );

         //Add to Group look up
         m_GroupMap.insert( make_pair(Resource->getGroup(), Resource ) );

         ++it;
      }

   }

   return true;
}

bool wiigi::c_ResourceMgr::loadScript( const std::string& ScriptName, std::list<c_Resource*>& NewResources )
{
   bool Success = false;
   
   NewResources.clear();

   XMLNode Root=XMLNode::parseFile( ScriptName.c_str(), "script" );
   
   if( !Root.isEmpty() )
   {
      const int NumOfEntrys = Root.nChildNode();

      for( int Idx = 0; Idx < NumOfEntrys; Idx++ )
      {
         XMLNode Node = Root.getChildNode( Idx );

         std::string NodeName( Node.getName() );

         if( NodeName == "resource" )
         {
            c_Resource* Resource;
            Resource = createResource( Node );
            if( Resource != 0 )
            {

               NewResources.push_back( Resource );
            }
         }

      }

      Success = true;
   }
   
   return Success;
}


wiigi::c_Resource* wiigi::c_ResourceMgr::createResource( XMLNode& ResourceNode )
{
   //Step 1
   //Check check if this node has an attribute called 'type'
   const std::string ResourceType( ResourceNode.getAttribute( "type" ) );

   c_Resource* Resource;
   Resource = c_Resource::createResource( this, ResourceType );
   if( Resource != 0 )
   {
      const int ChildNodeCnt = ResourceNode.nChildNode();

      for( int Idx = 0; Idx < ChildNodeCnt; Idx++ )
      {
         XMLNode ParameterNode = ResourceNode.getChildNode( Idx );

         const std::string ParameterName  = ParameterNode.getName();
         const std::string ParameterValue = ParameterNode.getText();
         
         if( Resource->setParameter( ParameterName, ParameterValue ) != true )
         {
            //printf( "Unsupported Parameter %s (%s)\n", ParameterName.c_str(), ParameterValue.c_str() );
         }

      }

   }
   else
   {
      printf( "Resource Type of \"%s\" is unkown\n", ResourceType.c_str() );
   }
   
   return Resource;
}

bool wiigi::c_ResourceMgr::cacheGroup( const std::string& GroupName )
{
   printf("c_ResourceMgr::cacheGroup:%s\n", GroupName.c_str() );
   
   std::multimap< std::string, c_Resource* >::iterator it;

   for( it = m_GroupMap.find( GroupName ); it != m_GroupMap.end(); it++ )
   {
      c_Resource* Resource;
      Resource = it->second;
      
      Resource->cache();
   }
   
   return true;
}

bool wiigi::c_ResourceMgr::purgeGroup( const std::string& GroupName )
{
   std::multimap< std::string, c_Resource* >::iterator it;

   for( it = m_GroupMap.find( GroupName ); it != m_GroupMap.end(); it++ )
   {
      c_Resource* Resource;
      Resource = it->second;
      
      Resource->purge();
   }

   return true;
}

void wiigi::c_ResourceMgr::deleteResources( void )
{
   for( std::list<c_Resource*>::iterator it = m_Resources.begin(); it != m_Resources.end(); ++it )
   {
      c_Resource* Resource;
      Resource = *it;
      assert( Resource != 0 );

      delete Resource;
   }

   m_Resources.clear();
}

wiigi::c_Sprite* wiigi::c_ResourceMgr::createSprite( const std::string& SpriteName )
{
   printf("RM::createSprite(): %s\n", SpriteName.c_str() );
   
   c_Sprite* Sprite;
   Sprite = 0;

   c_Resource* Resource;
   Resource = m_NameMap[ SpriteName ];
   if( Resource )
   {
      c_SpriteResource* SpriteResource = dynamic_cast<c_SpriteResource*>(Resource);
      if( SpriteResource )
      {
         Sprite = SpriteResource->createSprite();
      }
   }
   
   return Sprite;
}

bool wiigi::c_ResourceMgr::freeSprite( const std::string& SpriteName, c_Sprite* Sprite )
{
   c_Resource* Resource;
   Resource = m_NameMap[ SpriteName ];
   if( Resource )
   {
      c_SpriteResource* SpriteResource = dynamic_cast<c_SpriteResource*>(Resource);
      if( SpriteResource )
      {
         return SpriteResource->freeSprite( Sprite );
      }
   }
   
   return false;
}

wiigi::c_Texture* wiigi::c_ResourceMgr::getTexture( const std::string& TextureName )
{
   c_Texture* Texture;
   Texture = 0;

   c_Resource* Resource;
   Resource = m_NameMap[ TextureName ];
   if( Resource )
   {
      c_TextureResource* TextureResource = dynamic_cast<c_TextureResource*>(Resource);
      if( TextureResource )
      {
         Texture = TextureResource->getTexture();
      }
   }
   
   printf("RM:getTexture(): %s = %p\n", TextureName.c_str(), Texture );
   
   return Texture;
}
